package com.funsport.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.funsport.dto.request.VenueBookingRequest;
import com.funsport.dto.response.AvailableTimeSlot;
import com.funsport.dto.response.VenueBookingResponse;
import com.funsport.entity.User;
import com.funsport.entity.Venue;
import com.funsport.entity.VenueBooking;
import com.funsport.entity.Event;
import com.funsport.mapper.VenueBookingMapper;
import com.funsport.service.IVenueBookingService;
import com.funsport.service.IVenueService;
import com.funsport.service.IUserService;
import com.funsport.service.IEventService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 场地预订服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class VenueBookingServiceImpl extends ServiceImpl<VenueBookingMapper, VenueBooking> implements IVenueBookingService {
    
    private final IVenueService venueService;
    private final IUserService userService;
    private final IEventService eventService;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createBooking(VenueBookingRequest request, Long userId) {
        log.info("创建场地预订，场地ID: {}, 用户ID: {}", request.getVenueId(), userId);
        
        // 1. 验证场地存在
        Venue venue = venueService.getById(request.getVenueId());
        if (venue == null) {
            throw new RuntimeException("场地不存在");
        }
        
        // 2. 验证时间有效性
        if (request.getStartTime().isAfter(request.getEndTime())) {
            throw new RuntimeException("开始时间不能晚于结束时间");
        }
        
        if (request.getStartTime().isBefore(LocalDateTime.now())) {
            throw new RuntimeException("预订时间不能早于当前时间");
        }
        
        // 3. 检查时间冲突
        if (hasTimeConflict(request.getVenueId(), request.getStartTime(), request.getEndTime(), null)) {
            throw new RuntimeException("该时间段已被预订，请选择其他时间");
        }
        
        // 4. 计算价格（简单按小时计算）
        Duration duration = Duration.between(request.getStartTime(), request.getEndTime());
        double hours = duration.toMinutes() / 60.0;
        // Default price: 100 RMB per hour
        BigDecimal pricePerHour = new BigDecimal("100.00");
        BigDecimal price = pricePerHour.multiply(BigDecimal.valueOf(hours));
        
        // 5. 创建预订记录
        VenueBooking booking = new VenueBooking();
        booking.setVenueId(request.getVenueId());
        booking.setUserId(userId);
        booking.setEventId(request.getEventId());
        booking.setStartTime(request.getStartTime());
        booking.setEndTime(request.getEndTime());
        booking.setPrice(price);
        booking.setStatus("pending");
        booking.setPaymentStatus("unpaid");
        booking.setContactName(request.getContactName());
        booking.setContactPhone(request.getContactPhone());
        booking.setNotes(request.getNotes());
        
        this.save(booking);
        
        log.info("场地预订创建成功，预订ID: {}", booking.getId());
        return booking.getId();
    }
    
    @Override
    public VenueBookingResponse getBookingDetail(Long bookingId) {
        VenueBooking booking = this.getById(bookingId);
        if (booking == null) {
            throw new RuntimeException("预订不存在");
        }
        return convertToResponse(booking);
    }
    
    @Override
    public Page<VenueBookingResponse> getUserBookings(Long userId, Integer page, Integer pageSize, String status) {
        LambdaQueryWrapper<VenueBooking> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VenueBooking::getUserId, userId);
        
        if (status != null && !status.isEmpty()) {
            wrapper.eq(VenueBooking::getStatus, status);
        }
        
        wrapper.orderByDesc(VenueBooking::getCreatedAt);
        
        Page<VenueBooking> bookingPage = this.page(new Page<>(page, pageSize), wrapper);
        
        Page<VenueBookingResponse> responsePage = new Page<>(bookingPage.getCurrent(), bookingPage.getSize(), bookingPage.getTotal());
        responsePage.setRecords(
            bookingPage.getRecords().stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList())
        );
        
        return responsePage;
    }
    
    @Override
    public Page<VenueBookingResponse> getVenueBookings(Long venueId, Integer page, Integer pageSize, String status) {
        LambdaQueryWrapper<VenueBooking> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VenueBooking::getVenueId, venueId);
        
        if (status != null && !status.isEmpty()) {
            wrapper.eq(VenueBooking::getStatus, status);
        }
        
        wrapper.orderByDesc(VenueBooking::getCreatedAt);
        
        Page<VenueBooking> bookingPage = this.page(new Page<>(page, pageSize), wrapper);
        
        Page<VenueBookingResponse> responsePage = new Page<>(bookingPage.getCurrent(), bookingPage.getSize(), bookingPage.getTotal());
        responsePage.setRecords(
            bookingPage.getRecords().stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList())
        );
        
        return responsePage;
    }
    
    @Override
    public Page<VenueBookingResponse> getAllBookings(Integer page, Integer pageSize, String status, Long venueId, Long userId) {
        LambdaQueryWrapper<VenueBooking> wrapper = new LambdaQueryWrapper<>();
        
        if (status != null && !status.isEmpty()) {
            wrapper.eq(VenueBooking::getStatus, status);
        }
        
        if (venueId != null) {
            wrapper.eq(VenueBooking::getVenueId, venueId);
        }
        
        if (userId != null) {
            wrapper.eq(VenueBooking::getUserId, userId);
        }
        
        wrapper.orderByDesc(VenueBooking::getCreatedAt);
        
        Page<VenueBooking> bookingPage = this.page(new Page<>(page, pageSize), wrapper);
        
        Page<VenueBookingResponse> responsePage = new Page<>(bookingPage.getCurrent(), bookingPage.getSize(), bookingPage.getTotal());
        responsePage.setRecords(
            bookingPage.getRecords().stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList())
        );
        
        return responsePage;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirmBooking(Long bookingId, Long operatorId) {
        VenueBooking booking = this.getById(bookingId);
        if (booking == null) {
            throw new RuntimeException("预订不存在");
        }
        
        if (!"pending".equals(booking.getStatus())) {
            throw new RuntimeException("只能确认待确认的预订");
        }
        
        booking.setStatus("confirmed");
        booking.setConfirmedAt(LocalDateTime.now());
        this.updateById(booking);
        
        log.info("预订已确认，预订ID: {}, 操作人: {}", bookingId, operatorId);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelBooking(Long bookingId, Long userId) {
        VenueBooking booking = this.getById(bookingId);
        if (booking == null) {
            throw new RuntimeException("预订不存在");
        }
        
        if ("cancelled".equals(booking.getStatus()) || "completed".equals(booking.getStatus())) {
            throw new RuntimeException("该预订无法取消");
        }
        
        booking.setStatus("cancelled");
        booking.setCancelledAt(LocalDateTime.now());
        this.updateById(booking);
        
        log.info("预订已取消，预订ID: {}, 用户: {}", bookingId, userId);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeBooking(Long bookingId) {
        VenueBooking booking = this.getById(bookingId);
        if (booking == null) {
            throw new RuntimeException("预订不存在");
        }
        
        if (!"confirmed".equals(booking.getStatus())) {
            throw new RuntimeException("只能完成已确认的预订");
        }
        
        booking.setStatus("completed");
        this.updateById(booking);
        
        log.info("预订已完成，预订ID: {}", bookingId);
    }
    
    @Override
    public boolean hasTimeConflict(Long venueId, LocalDateTime startTime, LocalDateTime endTime, Long excludeBookingId) {
        int count = this.baseMapper.checkTimeConflict(venueId, startTime, endTime, excludeBookingId);
        return count > 0;
    }
    
    @Override
    public List<AvailableTimeSlot> getAvailableTimeSlots(Long venueId, LocalDateTime date) {
        // 获取当天所有预订
        List<VenueBooking> bookings = this.baseMapper.getBookingsByVenueAndDate(venueId, date);
        
        // 生成时间段（8:00-22:00，每小时一个时间段）
        List<AvailableTimeSlot> slots = new ArrayList<>();
        LocalDateTime dayStart = date.toLocalDate().atTime(8, 0);
        LocalDateTime dayEnd = date.toLocalDate().atTime(22, 0);
        
        LocalDateTime current = dayStart;
        while (current.isBefore(dayEnd)) {
            LocalDateTime slotEnd = current.plusHours(1);
            
            // 检查该时间段是否被占用
            boolean isAvailable = true;
            Long occupyingBookingId = null;
            
            for (VenueBooking booking : bookings) {
                if (current.isBefore(booking.getEndTime()) && slotEnd.isAfter(booking.getStartTime())) {
                    isAvailable = false;
                    occupyingBookingId = booking.getId();
                    break;
                }
            }
            
            slots.add(new AvailableTimeSlot(current, slotEnd, isAvailable, occupyingBookingId));
            current = slotEnd;
        }
        
        return slots;
    }
    
    @Override
    public List<VenueBookingResponse> getBookingsByDate(Long venueId, LocalDateTime date) {
        List<VenueBooking> bookings = this.baseMapper.getBookingsByVenueAndDate(venueId, date);
        return bookings.stream()
            .map(this::convertToResponse)
            .collect(Collectors.toList());
    }
    
    /**
     * 转换为响应DTO
     */
    private VenueBookingResponse convertToResponse(VenueBooking booking) {
        VenueBookingResponse response = new VenueBookingResponse();
        response.setId(booking.getId());
        response.setVenueId(booking.getVenueId());
        response.setUserId(booking.getUserId());
        response.setEventId(booking.getEventId());
        response.setStartTime(booking.getStartTime());
        response.setEndTime(booking.getEndTime());
        response.setPrice(booking.getPrice());
        response.setStatus(booking.getStatus());
        response.setPaymentStatus(booking.getPaymentStatus());
        response.setContactName(booking.getContactName());
        response.setContactPhone(booking.getContactPhone());
        response.setNotes(booking.getNotes());
        response.setCreatedAt(booking.getCreatedAt());
        response.setConfirmedAt(booking.getConfirmedAt());
        response.setCancelledAt(booking.getCancelledAt());
        
        // 计算时长
        Duration duration = Duration.between(booking.getStartTime(), booking.getEndTime());
        response.setDuration(duration.toMinutes() / 60.0);
        
        // 设置状态文本
        response.setStatusText(getStatusText(booking.getStatus()));
        response.setPaymentStatusText(getPaymentStatusText(booking.getPaymentStatus()));
        
        // 补充场地信息
        try {
            Venue venue = venueService.getById(booking.getVenueId());
            if (venue != null) {
                response.setVenueName(venue.getName());
                response.setVenueAddress(venue.getAddress());
            }
        } catch (Exception e) {
            log.warn("获取场地信息失败: {}", e.getMessage());
        }
        
        // 补充用户信息
        try {
            User user = userService.getById(booking.getUserId());
            if (user != null) {
                response.setUserName(user.getNickname());
                response.setUserPhone(user.getPhone());
            }
        } catch (Exception e) {
            log.warn("获取用户信息失败: {}", e.getMessage());
        }
        
        // 补充活动信息
        if (booking.getEventId() != null) {
            try {
                Event event = eventService.getById(booking.getEventId());
                if (event != null) {
                    response.setEventName(event.getTitle());
                }
            } catch (Exception e) {
                log.warn("获取活动信息失败: {}", e.getMessage());
            }
        }
        
        return response;
    }
    
    private String getStatusText(String status) {
        switch (status) {
            case "pending": return "待确认";
            case "confirmed": return "已确认";
            case "cancelled": return "已取消";
            case "completed": return "已完成";
            default: return status;
        }
    }
    
    private String getPaymentStatusText(String paymentStatus) {
        switch (paymentStatus) {
            case "unpaid": return "未支付";
            case "paid": return "已支付";
            case "refunded": return "已退款";
            default: return paymentStatus;
        }
    }
}

